(function (global){
    let document = global?.document;
    if (!document) return console.error('缺少 document 对象！');
    let cacheStorage = global.localStorage;

    console.log('浏览器基础库，提供全局方法：s94_env、cache_load')

    const s94_env_default = "#格式：键=值。键建议大写\n#每行#开头或者值中#后面部分表示注释，如果值需要包含#，需要使用引号包裹";
    const s94_env_cache_key = 'cache_s94_env';
    const s94_env_pass = [9,4];

    console.log(`s94_env配置面板唤起方式，${s94_env_pass.map(v=>'连点'+v+'次').join(' -> ')} 【注1：间隔半秒内判定为连点；注2：中途操作失误等待1秒从头开始】`)

    /**环境变量。连续点击页面打开配置界面
     * @param {String} key 配置名
     * @param {*} [def] 配置不存在时，返回的默认值
     */
    function s94_env(key, def){
        if (!s94_env.data){
            s94_env.data = {};
            let content = cacheStorage.getItem(s94_env_cache_key);
            if(!content) {
                content = s94_env_default;
                cacheStorage.setItem(s94_env_cache_key, content);
            }
            s94_env.data = decodeEnv(content);
        }
        return typeof(s94_env.data[key]) === 'undefined' ? def : s94_env.data[key];
    }
    function decodeEnv(txt){
        const result = {};
        /**
         * 解析环境变量值的类型
         * @param {string} value - 原始字符串值
         * @returns {*} 解析后的值（可能是字符串、数字、布尔值、null或未定义）
         */
        function parseValue(value) {
            // 去除尾部注释
            value = value.replace(/#[^'"]*$/, '');

            // 空字符串
            if (value === '') return '';

            // 布尔值、null、undefined 处理
            let keys = ['true', 'false', 'null', 'undefined'];
            let values = [true, false, null, undefined];
            let i = keys.indexOf(value.toLowerCase());
            if (~i) return values[i];

            // 处理引号包裹的字符串（单引号或双引号）
            if ((value.startsWith('"') && value.endsWith('"')) ||
                (value.startsWith("'") && value.endsWith("'"))) {
                return value.substring(1, value.length - 1);
            }

            // 数字（整数或浮点数）
            let num = Number(value);
            if (!isNaN(num)) return num;

            // 默认返回字符串
            return value;
        }
        // 按行分割文本
        txt.split(/\r?\n/).forEach((line)=>{
            // 移除首尾空白字符
            line = line.trim();
            // 跳过空行和注释行（以# //开头的行）
            if (!line || /^(#|\/{2})/.test(line)) return;
            // 提取键值
            let ms = line.match(/^(\w+)\s*=\s*([\S\s]*)$/);
            if (ms){
                result[ms[1]] = parseValue(ms[2])
            }
        })
        return result;
    }
    function s94_env_init(){
        let num=0, timeout_id;
        let pass = s94_env_pass, index = 0;
        //根节点绑定事件用于触发，如果要避免，可以在html节点阻止click事件冒泡
        window.addEventListener('click', ()=>{
            clearTimeout(timeout_id);
            timeout_id = setTimeout(()=>{
                if (pass[index] === num) {
                    index++;
                }else {
                    index = 0;
                }
                if (index>=pass.length && confirm('是否打开配置界面')){
                    s94_env_open();
                }
                num = 0;
            }, 500);
            num++;
        }, {capture:true})
    }
    function s94_env_open(){
        if (!s94_env.outer){
            let content = cacheStorage.getItem(s94_env_cache_key) || s94_env_default;
            s94_env.outer = document.createElement('form');
            s94_env.outer.style = 'position: fixed;display: flex;flex-direction: column;z-index: 9999;left: 0;top: 0;bottom: 0;right: 0;background: #fff;padding: 3.5em 1em 2.5em;';
            s94_env.outer.innerHTML = `
<span style="position: absolute;top: 2em;right: 1em;cursor: pointer;" onclick="this.parentNode.style.display='none'">关闭</span>
<textarea name="content" style="width: 100%;flex-grow: 1;box-sizing: border-box;">${content}</textarea>
<div style="font-size: 0.8em;color: #f56c6c">格式：配置名=值。注意：1、每行为一个配置，以#或者//开头表示注释；2、所有配置的值都为字符串</div>
<div style="display: flex;justify-content: space-between;padding-top: 1em;">
  <input type="button" onclick="" value="清理缓存">
  <input type="submit" value="提交">
</div>`;
            document.querySelector('body').appendChild(s94_env.outer);
            let dom_content = s94_env.outer.querySelector('textarea');
            s94_env.outer.querySelector('input[type="button"]').addEventListener('click', function (){
                if (confirm('是否确定清除本地缓存的数据')){
                    cacheStorage.clear();
                    cacheStorage.setItem(s94_env_cache_key, dom_content.value);
                }
            })
            s94_env.outer.addEventListener('submit', function (e){
                e.stopPropagation();
                e.preventDefault();
                cacheStorage.setItem(s94_env_cache_key, dom_content.value);
                s94_env.data = false;
                s94_env.outer.style.display = 'none';
            })
        }else {
            s94_env.outer.style.display = 'flex';
        }
    }
    s94_env_init();



    /**缓存加载js、css文件
     * @param {String[]|String} src_list 文件地址
     */
    function cache_load(src_list){
        if (typeof src_list === 'string') src_list = [src_list];
        cache_load.src_list = src_list;
        let code_list = cache_load.init();
        // 运行代码
        code_list.forEach(function (row){
            let type = row.src.match(/\.(js|css)(\?|$)/i)?.[1];
            switch (type) {
                case 'css':{
                    let dom = document.createElement('style');
                    dom.innerHTML = row.code;
                    document.querySelector('head').appendChild(dom);
                }break;
                case 'js':{
                    let dom = document.createElement('script');
                    if (/(^|;|\s)(import|export)\s+/.test(row.code)) dom.type = 'module';
                    dom.innerHTML = row.code;
                    document.querySelector('head').appendChild(dom);
                }break;
            }
        })
    }
    cache_load.KEY_PREFIX = 'cache_load-5dDVPQaL';
    cache_load.init = function (refresh, save_time){
        save_time = save_time || (3600*24*30);
        //清理缓存
        let keys = [];
        for (let i = 0; i < cacheStorage.length; i++) { keys.push(localStorage.key(i)); }
        let src_list = cache_load.src_list || [];
        let code_map = {};
        let now = Date.now();
        let timeout = now + save_time*1000;
        // 遍历缓存，按需要移除缓存的代码，获取获取缓存代码
        keys.forEach((key)=>{
            if (key.indexOf(cache_load.KEY_PREFIX) === 0){
                let src = key.substring(cache_load.KEY_PREFIX.length);
                if (!~src_list.indexOf(src)) return cacheStorage.removeItem(key);
                let data = cacheStorage.getItem(key);
                try { data = JSON.parse(data); } catch (e) {}
                if (!data || typeof data !== 'object' || !data.code) return cacheStorage.removeItem(key);
                data.src = src;
                code_map[src] = data;
            }
        })
        // 加载文件
        let loading = 0, need_reload = Object.keys(code_map).length!==src_list.length;
        src_list.forEach((src)=>{
            let code_row = code_map[src];
            // 如果代码没过期，并且没有刷新命令的情况下，跳过
            if (code_row && code_row.timeout>now && !refresh) return;
            loading++;
            let xhr = new XMLHttpRequest();
            xhr.open('get', src);
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.onload = function (){
                if (/^\s*</.test(xhr.responseText)) alert('页面加载异常');
                let cache_name = cache_load.KEY_PREFIX + src;
                cacheStorage.setItem(cache_name, JSON.stringify({code:xhr.responseText, timeout:timeout}));
                if (--loading <= 0 && need_reload) global.location.reload();
            }
            xhr.onerror = function (e){
                if(need_reload) alert(`页面加载出错：${e.message}`)
            }
            xhr.send();
        });
        // 返回代码列表
        return need_reload ? [] : Object.values(code_map);
    }

    global.s94_env = s94_env;
    global.cache_load = cache_load;

    return {s94_env,cache_load};
})(typeof globalThis !== 'undefined' ? globalThis :
    typeof self !== "undefined" ? self :
        typeof window !== "undefined" ? window :
            typeof global !== "undefined" ? global : {})
